import Taro from '@tarojs/taro'
import {platform} from './platform-settting.service'
import {BASE_URL, TARO_ENV, VC_LOG} from '../constants/api'
import {newHttp} from "./request";
import {h5Wx} from "./h5.service";
import {lxH5Wx} from "./lx.h5.service";

class LimitedParamsClass {
  params: string[][] = []
}

const limitedParams = new LimitedParamsClass()

/**
 * 获取url字符串参数
 */
const getParamFromUrlString = (urlString: string) => {
  let ret: string[][] = []
  if (urlString.indexOf('&') > -1) {
    const zi = urlString.split('&')
    if (zi.length > 0) {
      zi.map(item => {
        if (item.indexOf('=') > -1) {
          ret.push(item.split('='))
        }
      })
    }
  } else {
    if (urlString.indexOf('=') > -1) {
      const res = urlString.split('=')
      ret = [res]
    }
  }
  return ret
}

const displayModel = (content) => {
  Taro.showModal({
    content,
    title: '',
    showCancel: false
  })
}

const handlerNavigateTo = async (url) => {
  try {
    await Taro.navigateTo({
      url
    })
  } catch (e) {
    if (e.errMsg.endsWith('is not in app.json')) {
      displayModel('暂不支持，敬请期待')
    }
    if (e.errMsg.startsWith('navigateTo:fail Can not find proper registered route for')) {
      displayModel('链接地址不存在')
      setTimeout(() => Taro.navigateBack({delta: 1}), 2000)
    }
  }
}

// 将类似于 url 的字符串拆分成 key:value 形式的对象  例: pages/index/big?oid=123456&name=123 => { oid: '123456', name: '123', link: 'pages/index/big' }
const likeUrlStrSplitToObj = (url: string) => {
  const obj: {[key: string]: string} = {};
  const splitStr = url.split("?")
  const str = splitStr[1].split("&");
  for (let i = 0; i < str.length; i++) {
    const a = str[i].split('=')
    obj[a[0]] = a[1]
  }
  obj.link = splitStr[0]
  return obj
}

const gotoPage = async (url: string | undefined) => {
  if (!url) {
    return false
  }
  if (url.startsWith('lssmartcity://') || url.startsWith('/lssmartcity://')) {
    if (url.indexOf('/') === 0) {
      url = url.substr(1, url.length)
    }
    if (process.env.P_ENV === 'lx' && process.env.TARO_ENV !== 'h5') {
      url = decodeURIComponent(url)
      const lxDoMain = `lssmartcity://lsweb?url=http://wenlv-h5${process.env.NODE_ENV === 'production' ? '' : '-test'}.lx-internet.com`
      if (url.startsWith(lxDoMain)) {
        url = url.replace(lxDoMain, '')
      } else {
        return Taro.showToast({title: '请移步灵锡APP的文旅版块', icon: "none", mask: true, duration: 3000})
      }
    }
    if (process.env.TARO_ENV === 'h5') {
      if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) { // iOS
        window.location.href = url
      } else {
        lxH5Wx.jump(url)
      }
      return false
    }
  }
  if (process.env.P_ENV === 'lx' && url.indexOf('oid=') > -1) {
    const splitUrlObj: {[key: string]: string} = likeUrlStrSplitToObj(url)
    if(process.env.TARO_ENV === 'h5') {
      return lxH5Wx.openWeChatApplet(splitUrlObj.oid, splitUrlObj.link)
    }else {
      // 智能导览(无锡全域智能导览小程序)
      if(url.indexOf("gh_") > -1) {
        Taro.navigateToMiniProgram({
          appId: splitUrlObj.appid,
          path: splitUrlObj.link
        })
      }
    }
  }
  if (/pages\/index\/big/.test(url)|| /page\/qianggou\/index\/index/.test(url) || /pages\/index\/index/.test(url) || /pages\/my\/index\/index/.test(url) || /page\/index/.test(url)) {
    if (/page\/qianggou\/index\/index/.test(url) && url.indexOf('?') > -1) {
      const urlParam = url.split('?')
      limitedParams.params = getParamFromUrlString(urlParam[1])
      url = '/common/limited/index?' + urlParam[1]
    }
    if (/common/.test(url)) {
      await handlerNavigateTo(url)
    } else {
      try {
        await Taro.reLaunch({
          url
        })
      } catch (e) {
        if (e.errMsg.endsWith('is not in app.json')) {
          displayModel('暂不支持，敬请期待')
        }
      }
    }
  } else {
    await handlerNavigateTo(url)
  }
}

/**
 * h5模式获取路由参数
 * @param d
 */
const GetRequest = (d) => {
  let theRequest: any = {}
  if (process.env.TARO_ENV === 'h5') {
    const url = window.location.search;   //获取url中"?"符后的字串
    if (url.indexOf("?") != -1) {
      const str = url.substr(1);
      const strs = str.split("&");
      for (let i = 0; i < strs.length; i++) {
        theRequest[strs[i].split("=")[0]] = decodeURIComponent(strs[i].split("=")[1]);
      }
    }
  } else {
    if (typeof (d) != "undefined" && typeof (d.$router) != "undefined") {
      if (d.$router.params.label) {
        d.$router.params.label = decodeURIComponent(d.$router.params.label)
      }
      theRequest = d.$router.params
    }
  }
  if (JSON.stringify(theRequest) == '{}') {
    theRequest = false
  }
  return theRequest;
}

const replaceUrl = (url, arg, val) => {
  const pattern = arg + '=([^&]*)';
  const replaceText = arg + '=' + val;
  return url.match(pattern) ? url.replace(eval('/(' + arg + '=)([^&]*)/gi'), replaceText) : (url.match('[\?]') ? url + '&' + replaceText : url + '?' + replaceText);
}

const getTokenFromCookies = (cookies, userInfo: any = '') => {
  if (userInfo && Taro.getCurrentInstance().router.params.pkeys) {
    return userInfo.token
  }
  if (process.env.NODE_ENV === 'development') {
    return 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJ7XCJ1c2VySWRcIjoxMTY0MzEwfSIsImV4cCI6MTY3MjIxNDM5NywiaWF0IjoxNjY5NjIyMzk3fQ._adpAscPorIyQshCD9chnt7jNjgeB0lDB99ie19QjPU'
  }
  const arrCookies = cookies.replace(/\s+/g, '').split(";");//分割
  //遍历匹配
  for (let i = 0; i < arrCookies.length; i++) {
    const arr = arrCookies[i].split("=");
    if (arr[0] == 'token') {
      return arr[1];
    }
  }
}

function vcnull(obj) {
  return typeof (obj != 'undefined') && null != obj && obj != '';
}

function uuid2() {
  const s: any = [];
  const hexDigits = "0123456789abcdef";
  for (let i = 0; i < 32; i++) {
    s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
  }
  s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
  s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
  s[8] = s[13] = s[18] = s[23];
  return s.join("");
}

export const setTempSellerId = (tempSellerId) => {
  const key = process.env.TARO_ENV + '_' + process.env.P_ENV + '_tempSellerId';
  Taro.setStorageSync(key, tempSellerId)
}

/**
 * 获取临时分销商ID
 */
export const getTempSellerId = (objThis = {}) => {
  const key = process.env.TARO_ENV + '_' + process.env.P_ENV + '_tempSellerId';
  let tempSellerId = GetRequest(objThis).tempSellerId
  //如果url上有，写入tempSellerId
  if (typeof (tempSellerId) != 'undefined' && tempSellerId != '') {
    setTempSellerId(tempSellerId)
  } else {
    tempSellerId = Taro.getStorageSync(key)
  }
  if (typeof (tempSellerId) === 'undefined') {
    tempSellerId = ''
  }
  return tempSellerId;
}

export const getPageUrl = () => {
  let url = ''
  if (process.env.TARO_ENV === 'h5') {
    url = window.location.href;
  } else {
    const pages = Taro.getCurrentPages();
    const currentPage = pages[pages.length - 1]
    if (typeof (currentPage) != 'undefined' && typeof (currentPage.$router != 'undefined')) {
      const _router = currentPage
      if (typeof (_router) != "undefined" && typeof (_router.route) != "undefined" && null != _router.route) {
        url = _router.route;
      }
      if (typeof (_router) != "undefined" && typeof (_router.options) != "undefined" && null != _router.options) {
        const _params = _router.options;
        if (typeof (_params) != 'undefined' && null != _params) {
          url = url + '?';
          for (const k in _params) {
            url += k + "=" + _params[k] + "&"
          }
          url = url.substring(0, url.length - 1);
        }
      }
    }
  }
  return url;
}

/**
 * 获取当前页的url参数
 */
export const getPageParams = () => {
  let params = '';
  if (process.env.TARO_ENV === 'h5') {
    params = window.location.search;
  } else {
    const pages = Taro.getCurrentPages();
    const currentPage = pages[pages.length - 1]
    if (currentPage && (currentPage.$router || currentPage.route)) {
      const _router = currentPage.$router || currentPage.route
      let _params
      if (process.env.TARO_ENV === 'tt') {
        _params = currentPage.options
      } else {
        _params = _router.params || currentPage.__displayReporter.query || currentPage.options
      }
      if (_params) {
        let mpkey = ''
        const uInfo = Taro.getStorageSync('user') || ''
        if (uInfo && uInfo.mpkey && uInfo.mpkey !== 'undefined') {
          mpkey = uInfo.mpkey
        }
        params = '?';
        for (const k in _params) {
          params += k + "=" + _params[k] + "&"
        }
        params = params + `&mpkey=${mpkey}`
        params = params.substring(0, params.length - 1);
      }
    }
  }
  return params;
}

const isPc = () => {
  return window.navigator.userAgent.toString().toLowerCase().includes('windowswechat')
}

/**
 * 每个页面都走的监听方法
 */
const vcmonitor = async (page, needConfig = true) => {
  const getRequest = GetRequest(page)
  if (TARO_ENV === 'weapp' && page && getRequest && getRequest.sKey) {
    Taro.setStorageSync('sKey', getRequest.sKey)
    platform.info = await platform.getSetting()
  }
  // 记录页面路径
  let pages
  pages = Taro.getStorageSync('pages')
  if (!pages) {
    pages = []
    Taro.setStorageSync('pages', pages)
  }
  const request = getPageUrl()
  // 当前页面刷新不记录日志
  if (pages.length > 0 && pages[pages.length - 1] === request) {
    return
  }
  const userInfo = Taro.getStorageSync('user')
  if (TARO_ENV === 'h5') {
    const mpkey = await Taro.getCurrentInstance().router.params.mpkey || ''
    if (mpkey && mpkey !== 'null' && mpkey !== null && userInfo) {
      userInfo['mpkey'] = mpkey
      Taro.setStorageSync('user', userInfo)
    }
  }
  if (process.env.TARO_ENV === 'h5' && document.location.pathname !== '/pay/success' && needConfig) {
    await h5Wx.getConfig()
  }
  // 如果没有登录
  if (TARO_ENV === 'weapp' && !userInfo) {
    await Taro.hideShareMenu()
  }
  setTimeout(async function () {
    let title = '';
    if (vcnull(page.config) && vcnull(page.config.navigationBarTitleText)) {
      title = page.config.navigationBarTitleText;
    } else if (vcnull(page.state) && vcnull(page.state.title)) {
      title = page.state.title;
    } else if (vcnull(page.state) && vcnull(page.state.itemName)) {
      title = page.state.itemName;
    } else if (vcnull(page.state) && vcnull(page.state.labelText)) {
      title = page.state.labelText;
    } else if (vcnull(page.state) && vcnull(page.state.news) && vcnull(page.state.news.title)) {
      title = page.state.news.title;
    } else if (vcnull(page.state) && vcnull(page.state.pageData) && vcnull(page.state.pageData.pageTitle)) {
      title = page.state.pageData.pageTitle;
    } else if (vcnull(page.state) && vcnull(page.state.pageData) && vcnull(page.state.pageData.custom_backGround) && vcnull(page.state.pageData.custom_backGround.title)) {
      title = page.state.pageData.custom_backGround.title;
    }
    const host = window && window.location.hostname;
    let p_key = ''
    let s_key = ''
    let mp_key = ''
    let scene = '';
    if (process.env.TARO_ENV === 'h5') {
      await h5Wx.hideCopyUrl()
      const extConfig = Taro.getStorageSync('user');
      const sKey = Taro.getStorageSync('sKey');
      p_key = extConfig.pkey;
      if (sKey) {
        s_key = sKey
      }
      mp_key = extConfig.mpkey;
    } else {//如果是小程序
      if (typeof (Taro.getLaunchOptionsSync()) != 'undefined' && typeof (Taro.getLaunchOptionsSync().scene) != 'undefined') {
        scene = Taro.getLaunchOptionsSync().scene + "";
      }
      const extConfig = Taro.getExtConfigSync();
      p_key = extConfig['p-key']
    }
    let session = '';
    let sessionObj = Taro.getStorageSync("sessionObj");
    let step = 1;
    //如果不为空
    if (typeof (sessionObj) != "undefined" && sessionObj != null && sessionObj != '') {
      const now = new Date();
      const lose = new Date(now.getTime() + 1000 * 60 * 30);
      const loseTime = sessionObj.loseTime
      if (now > loseTime) {//如果过期了，重新写入
        session = uuid2();
        //写入session
        sessionObj = {
          sessionId: session,
          loseTime: lose.getTime(),
          step: 1
        };
        Taro.setStorageSync("sessionObj", sessionObj);
      } else {//如果没有过期，进行续期
        session = sessionObj.sessionId;
        step = sessionObj.step;
        step = step + 1;
        //写入session
        sessionObj = {
          sessionId: session,
          loseTime: lose.getTime(),
          step: step
        };
        Taro.setStorageSync("sessionObj", sessionObj);
      }
    } else {
      const now = new Date();
      const lose = new Date(now.getTime() + 1000 * 60 * 30);
      //写入session
      sessionObj = {
        sessionId: uuid2(),
        loseTime: lose.getTime(),
        step: 1
      };
      Taro.setStorageSync("sessionObj", sessionObj);
    }
    step = sessionObj.step;

    // 维护pages列表
    let referer = ''
    // 如果新页面是当前页面的上一级， 算回退 (为了解决在支付页返回后paytoken找不到商品信息的问题)
    if (pages.length > 1 && pages[pages.length - 2] === request) {
      pages.pop()
      if (pages.length > 1) {
        referer = pages[pages.length - 2]
      }
    } else {
      if (pages.length > 0) {
        referer = pages[pages.length - 1]
      }
      pages.push(request)
    }
    while (pages.length > 10) {
      pages.shift()
    }
    Taro.setStorageSync("pages", pages)

    newHttp.post(BASE_URL + VC_LOG, {
      title,
      host,
      p_key,
      s_key,
      mp_key,
      referer,
      step,
      request,
      session,
      scene,
      foundation: process.env.TARO_ENV || '',
    }, false);
  }, 1500);
}

/**
 * 判断字符串长度（英文占1个字符，中文汉字占2个字符）
 * @param str
 */
const strlen = (str: string) => {
  let len = 0;
  for (let i = 0; i < str.length; i++) {
    const c = str.charCodeAt(i);
    //单字节加1
    if ((c >= 0x0001 && c <= 0x007e) || (0xff60 <= c && c <= 0xff9f)) {
      len++;
    } else {
      len += 2;
    }
  }
  return len;
}

const zero = (num: number): string => {
  if (num > 0) {
    return num < 10 ? `0${num}` : `${num}`
  } else {
    return '00'
  }
}

let menuInfonum = 0
const getmenuif = () => {
  const menuInfo = process.env.TARO_ENV !== 'h5' ? Taro.getMenuButtonBoundingClientRect() : {
    top: 20
  }
  if (menuInfo.top == 0 && menuInfonum < 10) {
    menuInfonum++
    return getmenuif()
  } else {
    return menuInfo
  }
}

const getHeadTop = (): { statusBar: number; top: number } | false => {
  if (platform.customTitleBar) {
    return platform.customTitleBar
  }
  if (process.env.TARO_ENV === "weapp") {
    try {
      const systemInfo = Taro.getSystemInfoSync()
      const menuInfo = getmenuif()
      if (systemInfo && menuInfo) {
        platform.customTitleBar = {
          statusBar: systemInfo.statusBarHeight,
          top: menuInfo.top - systemInfo.statusBarHeight
        }
        return platform.customTitleBar
      }
    } catch (e) {
    }
  } else {
    platform.customTitleBar = {statusBar: 0, top: 12}
    return platform.customTitleBar
  }
  return false
}

const lastMinute = (time) => {
  const nowTime = new Date().getTime()
  return time - nowTime < 60 * 1000;
}

const calcTime = (millsFuture, nowMills) => {
  const future = millsFuture || (Date.UTC(2050, 0, 1) - 480 * 60 * 1000);
  //现在将来秒差值
  const dur = Math.round((future - nowMills) / 1000);
  const pms = {
    dur: dur,
    day: "00",
    hour: "00",
    minute: "00",
    second: "00",
    month: "00",
    year: "0"
  };
  if (dur > 0) {
    pms.second = zero(dur % 60);
    pms.minute = Math.floor((dur / 60)) > 0 ? zero(Math.floor((dur / 60)) % 60) : "00";
    pms.hour = Math.floor((dur / 3600)) > 0 ? zero(Math.floor((dur / 3600)) % 24) : "00";
    pms.day = Math.floor((dur / 86400)) > 0 ? zero(Math.floor((dur / 86400))) : "00";
    //月份，以实际平均每月秒数计算
    pms.month = Math.floor((dur / 2629744)) > 0 ? zero(Math.floor((dur / 2629744)) % 12) : "00";
    //年份，按按回归年365天5时48分46秒算
    pms.year = Math.floor((dur / 31556926)) > 0 ? Math.floor((dur / 31556926)) + '' : "0";
  }
  return pms;
}
const toIosDateFormat = (date: string) => {
  if (date.includes('-')) {
    return date.replace(/\-/g, '/')
  }
  return date
}
/**
 * 破折号命名转小驼峰
 */
const convert2CamelCase = (name = ''): string => {
  const nameTemp = name.split('-');
  let ret = nameTemp[0] || '';
  for (let i = 1; i < nameTemp.length; i++) {
    ret += nameTemp[i].slice(0, 1).toUpperCase() + nameTemp[i].slice(1) || '';
  }
  return ret;
}

const formatNumber = n => {
  n = n.toString()
  return n[1] ? n : '0' + n
}

// 时间戳转时间
const formatTime = thisDate => {
  const date = new Date(thisDate)//一定要记得写这个，不然会报date.getFullYear is not a function
  const month = date.getMonth() + 1
  const day = date.getDate()
  const hour = date.getHours()
  const minute = date.getMinutes()
  return [month, day].map(formatNumber).join('/') + ' ' + [hour, minute].map(formatNumber).join(':')
}

/*函数节流*/
const throttle = (fn, interval) => {
  let enterTime = 0;//触发的时间
  const gapTime = interval || 300;//间隔时间，如果interval不传，则默认300ms
  return function () {
    const context = this;
    const backTime: any = new Date();//第一次函数return即触发的时间
    if (backTime - enterTime > gapTime) {
      fn.call(context, arguments);
      enterTime = backTime;//赋值给第一次触发的时间，这样就保存了第二次触发的时间
    }
  };
}

/*函数防抖*/
const debounce = (fn, interval) => {
  let timer;
  const gapTime = interval || 200;//间隔时间，如果interval不传，则默认1000ms
  return function () {
    clearTimeout(timer);
    const context = this;
    const args = arguments;//保存此处的arguments，因为setTimeout是全局的，arguments不是防抖函数需要的。
    timer = setTimeout(function () {
      fn.call(context, args);
    }, gapTime);
  };
}

/* 倒叙时间 */
const beforeTime = (dateTimeStamp) => {
  const minute = 1000 * 60; //把分，时，天，周，半个月，一个月用毫秒表示
  const hour = minute * 60;
  const day = hour * 24;
  const week = day * 7;
  const month = day * 30;
  const year = day * 365;
  const now = new Date().getTime(); //获取当前时间毫秒
  const diffValue = now - dateTimeStamp; //时间差
  if (diffValue < 0) {
    return;
  }
  const minC = diffValue / minute; //计算时间差的分，时，天，周，月
  const hourC = diffValue / hour;
  const dayC = diffValue / day;
  const weekC = diffValue / week;
  const monthC = diffValue / month;
  const yearC = diffValue / year;
  let result;
  if (yearC >= 1) {
    result = " " + parseInt(yearC) + "年前";
  } else if (monthC >= 1 && monthC <= 12) {
    result = " " + parseInt(monthC) + "月前";
  } else if (weekC >= 1 && weekC <= 4) {
    result = " " + parseInt(weekC) + "周前";
  } else if (dayC >= 1 && dayC <= 7) {
    result = " " + parseInt(dayC) + "天前";
  } else if (hourC >= 1 && hourC <= 24) {
    result = " " + parseInt(hourC) + "小时前";
  } else if (minC >= 1 && minC <= 60) {
    result = " " + parseInt(minC) + "分钟前";
  } else if (diffValue >= 0 && diffValue <= minute) {
    result = "刚刚";
  } else {
  }
  return result;
}

const deepClone = (source) => {
  const targetObj = source.constructor === Array ? [] : {};
  Object.keys(source).forEach(keys => {
    if (source[keys] && typeof source[keys] === 'object') {
      targetObj[keys] = deepClone(source[keys]);
    } else {
      targetObj[keys] = source[keys];
    }
  });
  return targetObj;
}
/**
* 入口-搜索框

  搜索页面
    1. 是否有详情页的缓存关键字：有 - 移除详情缓存，设置新的搜索缓存
    2. 由 Category 组件传递"区别搜索的参数内容"

  搜索关键字
    有 - 缓存关键字

  详情页
    H5: 有缓存关键字 - 重新设置缓存关键字，移除原缓存关键字
**/
const keepSearch = () => {
  const fromWhere = Taro.getStorageSync("fromWhere");
  if(!!fromWhere) {
    Taro.setStorageSync("fromDetail", fromWhere);
    Taro.removeStorageSync("fromWhere");
  }else {
    Taro.removeStorageSync("fromDetail");
  }
}
const clearSearch = () => {
  !!Taro.getStorageSync("fromWhere") && Taro.removeStorageSync("fromWhere");
  !!Taro.getStorageSync("fromDetail") && Taro.removeStorageSync("fromDetail");
  !!Taro.getStorageSync("categoryList") && Taro.removeStorageSync("categoryList");
  !!Taro.getStorageSync("pageScrollTop") && Taro.removeStorageSync("pageScrollTop");
  !!Taro.getStorageSync("canPageScroll") && Taro.removeStorageSync("canPageScroll");
}

/**
 * 缓存存储工具
 * @param key 对象key
 * @param obj 缓存对象
 * @param time 超时时间（秒）
 */
const vcSetCache = (key, obj, time) => {
  const curTime = new Date();
  curTime.setSeconds(curTime.getSeconds() + time);
  const cacheObj = {
    data: obj,
    time: curTime.getTime()
  }
  Taro.setStorageSync(key, cacheObj);
}

/**
 * 缓存查询工具
 * @param key 缓存key
 */
const vcGetCache = (key) => {
  const _obj = Taro.getStorageSync(key);
  if (null == _obj) {
    return null;
  }
  //取出超时时间来
  const _time = _obj.time;
  const now = new Date().getTime();
  //如果超时了，移除key
  if (_time < now) {
    Taro.removeStorageSync(key)
    return null;
  } else {
    return _obj.data;
  }
}

const getStorageSync = (key) =>{
  return Taro.getStorageSync(key) || ''
}

const setStorageSync = (key, value) =>{
  Taro.setStorageSync(key, value)
}

// 处理退款标签(取并集去重)
const dealRefundSign = (list: any = []) => {
    let tempArr = [], mapObj = [];
    for(let i = 0, len = list.length; i < len; i++) {
      const refund_sign = list[i].refund_sign ? list[i].refund_sign.split(",") : [];
      tempArr = tempArr.concat(refund_sign);
    }
    tempArr.map(item => {
      if(!!item) mapObj.push(item);
    })
    return Array.from(new Set(mapObj));
}

export {
  getStorageSync,
  setStorageSync,
  vcSetCache,
  vcGetCache,
  deepClone,
  beforeTime,
  gotoPage,
  strlen,
  zero,
  getHeadTop,
  lastMinute,
  calcTime,
  toIosDateFormat,
  limitedParams,
  GetRequest,
  getTokenFromCookies,
  convert2CamelCase,
  formatTime,
  debounce,
  throttle,
  vcmonitor,
  replaceUrl,
  isPc,
  keepSearch,
  clearSearch,
  dealRefundSign
}
